#include "CheckingAccount.hh"
#include "AccountUtils.hh"
#include "BankSystem.hh"
#include "Transaction.hh"
#include "IO.hh"
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <ctime>

namespace {
    std::string getCurrentDate() {
        std::time_t now = std::time(nullptr);
        char buffer[11];
        std::strftime(buffer, sizeof(buffer), "%Y-%m-%d", std::localtime(&now));
        return buffer;}}
    namespace Bank {

    CheckingAccount::CheckingAccount(const std::string& id, const std::string& owner, double initialBalance)
        : accountId(id), ownerName(owner), balance(initialBalance) {}

    std::string CheckingAccount::getAccountId() const { return accountId; }
    std::string CheckingAccount::getOwnerName() const { return ownerName; }
    std::string CheckingAccount::getFormattedBalance() const {
        std::ostringstream oss;
        oss << "(CNY)" << std::fixed << std::setprecision(2) << balance;
        return oss.str();}

    std::string CheckingAccount::getAccountType() const { return "Checking"; }
    double CheckingAccount::getBalance() const { return balance; }
//After executing the transfer, reduce the current account balance and call the interface for the target account to receive the transfer.
    bool CheckingAccount::transferTo(IAccount* toAccount, double amount, const std::string& note) {
        if (amount <= 0) return std::cout << "Invalid transfer amount.\n", false;
        if (amount > balance) return std::cout << "Insufficient balance for transfer!\n", false;
        balance -= amount;
        toAccount->receiveTransfer(amount);
        std::cout << "Transfer successful from " << accountId << " to " << toAccount->getAccountId() << "\n";
        return true;}

    void CheckingAccount::displayInfo() const {
        std::cout << "Checking Account: " << accountId << "\n"<< "Owner: " << ownerName << "\n"<< "Balance: " << getFormattedBalance() << "\n";}
//Every time a deposit is made, a 'Deposit' type transaction record is created and entered into the system.
    void CheckingAccount::deposit(double amount) {
        if (amount <= 0) return std::cout << "Invalid deposit amount.\n", void();
        balance += amount;
        std::cout << "Deposited (CNY)" << amount << " to " << accountId << ". New balance: " << getFormattedBalance() << "\n";
        Transaction tx(Transaction::generateUniqueTransactionID(), TransactionType::Deposit, amount, accountId);
        BankSystem::getInstance().recordTransaction(tx);}

    bool CheckingAccount::withdraw(double amount) {
        if (amount <= 0) return std::cout << "Invalid withdrawal amount.\n", false;
        if (amount > balance) return std::cout << "Insufficient balance in checking account.\n", false;
        balance -= amount;
        std::cout << "Withdrew (CNY)" << amount << " from checking account [" << accountId << "].\n";
        Transaction tx(Transaction::generateUniqueTransactionID(), TransactionType::Withdraw, amount, accountId);
        BankSystem::getInstance().recordTransaction(tx);
        return true;}

    void CheckingAccount::receiveTransfer(double amount) {
        if (amount > 0) {
            balance += amount;
            std::cout << "Received transfer of " << amount << " to checking account " << accountId << "\n";}
    }

    void CheckingAccount::accessAccountInterface(const std::string& customerName, const std::vector<Transaction>& allTransactions) {
        while (true) {
            std::cout << "\n===== Bank Account: " << accountId << " (Checking Account) =====\n"<< "Account holder: " << customerName << "\n"<< "Balance: " << getFormattedBalance() << "\n\n"
                    << "1. Deposit\n2. Withdraw\n3. Transfer\n4. View transaction history\n"<< "5. Generate bank account report\n6. Return to customer page\nPlease choose: ";

            int choice = IO::getNumber();
            if (choice == 6) return;

            if (choice == 1) {
                std::cout << "Enter deposit amount: ";
                double amount = IO::getAmount();
                deposit(amount);
            } else if (choice == 2) {
                std::cout << "Enter withdrawal amount: ";
                double amount = IO::getAmount();
                if (withdraw(amount))
                    std::cout << "Withdrawal successful!\n";
                else
                    std::cout << "Withdrawal failed.\n";}
            //The transfer option calls the Transaction::performTransfer method, handling all validation and transaction logic.        
                else if (choice == 3) {
                std::cout << "Enter target account ID: ";
                std::string toAccountId = IO::getString();

                std::cout << "Enter amount to transfer: ";
                double amount = IO::getAmount();

                std::cout << "Enter note (optional): ";
                std::string note = IO::getString();

                Transaction::performTransfer(
                    BankSystem::getInstance(),
                    BankSystem::getInstance().findAccountById(accountId),
                    toAccountId,
                    amount,
                    note);
            } else if (choice == 4) {
                std::cout << "\n=== Transactions for account " << accountId << " ===\n";
                for (const auto& tx : allTransactions)
                    if (tx.involvesAccount(accountId)) std::cout << tx.toString() << "\n";
            } else if (choice == 5) {
                std::string filename = "transactions_" + accountId + "_" + getCurrentDate() + ".txt";
                std::ofstream outFile(filename);
                for (const auto& tx : allTransactions)
                    if (tx.involvesAccount(accountId)) outFile << tx.toString() << "\n";
                std::cout << "Report saved to: " << filename << "\n";
            } else {
                std::cout << "Invalid option.\n";
            }
        }
    }
}